package org.mar.integer;

public class IntGetChars {
    public static void main(String[] args) {
        assert "0".equals(new String(getChars(0, 1, new byte[1])));
        assert "1".equals(new String(getChars(1, 1, new byte[1])));
        assert "9".equals(new String(getChars(9, 1, new byte[1])));
        assert "10".equals(new String(getChars(10, 2, new byte[2])));
        assert "15".equals(new String(getChars(15, 2, new byte[2])));
        assert "100".equals(new String(getChars(100, 3, new byte[3])));
        assert "156".equals(new String(getChars(156, 3, new byte[3])));
        assert "-1".equals(new String(getChars(-1, 2, new byte[2])));
        assert "-15".equals(new String(getChars(-15, 3, new byte[3])));
    }

    /**
     * @see Integer getChars(int, int, byte[])
     * @param i
     * @param index
     * @param buf
     * @return 为了让测试用例更简洁，直接把参数的字节数组返回
     */
    private static byte[] getChars(int i, int index, byte[] buf) {
        boolean negative = true;
        if (i >= 0) {
            i = -i;
            negative = false;
        }

        // 三位数及以上，就每次处理两个末尾数字
        if (i <= -100) {
            int q = i / 100;
            int r = (q * 100) - i;  // 取十位个位
            i = q;
            // 这里都使用r作为下标，比如r=23，DigitTens[23]就是2，而在DigitOnes[23]则是3，就组合成了23，挺有意思的
            buf[--index] = DigitOnes[r];
            buf[--index] = DigitTens[r];
        }

//        here!
//        while (i < 0) {
//            int q = i / 10;
//            int r = (q * 10) - i;
//            buf[--index] = (byte)('0' + r);
//            i = q;
//        }

        // 这里分成两部分是为了处理当参数i==0的情况，如果换成上面的while循环无法处理i==0的情况，不信可以把这里注释掉换成上面的while跑一下
        // 因为写成while形式也需要额外处理，所以不如直接写成两部分
        // 只剩两位数
        int q = i / 10;
        int r = (q * 10) - i;
        buf[--index] = (byte)('0' + r);
        // 还剩一位数
        if (q < 0) {
            buf[--index] = (byte) ('0' - q);
        }

        // 给负数开头加个负号
        if (negative) {
            buf[--index] = '-';
        }
        return buf;
    }

    /**
     * 第一行下标对应0~9，所以如果下标在这个范围，表示是一个个位数，所以十位数为0
     * 第二行下标对应10~19，表示是一个1开头十位数，所以十位数为1，以此类推
     */
    static final byte[] DigitTens = {
            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
    };

    /**
     * 第一行下标对应0~9，第二行下标对应10~19，按下标取出的个位数就和下标个位一致
     */
    static final byte[] DigitOnes = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    };
}
